﻿using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace RabbitMQ.Gateway
{
    public abstract class BaseMessageConsumer :IMessageConsumer
    {
        /// <summary>
        /// 队列消费函数
        /// </summary>
        /// <param name="message">队列中的消息</param>
        /// <param name="channel">管道，用于消费处理后的ACK操作</param>
        /// <param name="header">消息交互头信息，ACK时定位消息</param>
        /// <param name="loger">log4net loger对象，调用RQConsumer.ConsumerStart启动消费服务时传入，如果为空则为root</param>
        /// <param name="ErrorMethod">异常处理函数 参数分别是
        /// 1.消息体
        /// 2.记录失败队列的Publiser对象，配置位于amqp.connection.config PublisherList 子节点name属性 及队列名
        /// 3.记录失败队列的Publiser对象，配置位于amqp.connection.config PublisherList 子节点routekey属性 及路由关键字
        /// 4.返回错误消息的推送状态
        /// </param>
        public abstract void ConsumeMessage(Message message, IModel channel, DeliveryHeader header,log4net.ILog loger,Func<object, string, string, bool> ErrorMethod);


        // protected log4net.ILog log = log4net.LogManager.GetLogger(typeof(BaseMessageConsumer));

        private readonly log4net.ILog parmlog = log4net.LogManager.GetLogger(typeof(BaseMessageConsumer));

        protected void LogAccessParm(object obj)
        {
            try
            {
                parmlog.Info("---------------------------------------------------");
                parmlog.Info(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(obj));
            }
            catch (Exception ex)
            {
                RabbitMQ.Gateway.Log.loger.Error(ex);
            }
        }

       
        /// <summary>
        /// 将消息转文本
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public string ConvertFromMessageToString(Message message)
        {
            var content = string.Empty;
            if (message.Properties.ContentType == Const.PLAIN_TEXT)
            {
                var encoding = Encoding.GetEncoding(message.Properties.ContentEncoding ?? "utf-8");
                var ms = new MemoryStream(message.Body);
                var reader = new StreamReader(ms, encoding, false);
                content = reader.ReadToEnd();
            }
            return content;
        }

        /// <summary>
        /// 将消息转对象
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public object ConvertFromMessageToObject(Message message)
        {
            object obj = null;
            if (message.Properties.ContentType == Const.PlAIN_OBJ)
            {
                //var encoding = Encoding.GetEncoding(message.Properties.ContentEncoding ?? "utf-8");
                obj = Serialization.ByteToObject(message.Body);
            }
            return obj;
        }

        /// <summary>
        /// 动态创建指定的类
        /// <remarks>该方法可以代替原来DALFactory中的各个数据访问接口的定义</remarks>
        /// </summary>
        /// <param name="sKey">配置文件中程序集的定义“键值”</param>
        /// <param name="sClass">数据类名</param>
        /// <returns></returns>
        private static object Create(string sPath, string sClass)
        {
            Assembly AssemblyDAL;
            AssemblyDAL = Assembly.Load(sPath);

            sClass = sPath + "." + sClass;
            object oEventBatch = AssemblyDAL.CreateInstance(sClass, true);

            return oEventBatch;
        }

        /// <summary>
        /// 反射的方式执行函数
        /// </summary>
        /// <param name="Assembly"></param>
        /// <param name="ClassName"></param>
        /// <param name="MethodName"></param>
        /// <param name="Parm"></param>
        protected static bool ExecuteMethod(string Assembly, string ClassName, string MethodName, object Parm)
        {
            string AssemblyName = getAssemblyByKey(Assembly);
            if (string.IsNullOrEmpty(AssemblyName))
            {
                return false;
            }
            try
            {
                object oEventBatch = Create(AssemblyName, ClassName);
                MethodInfo mi = oEventBatch.GetType().GetMethod(MethodName);
                mi.Invoke(oEventBatch, new object[] { Parm });
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return true;
        }

        /// <summary>
        /// 根据key,获取程序集名称
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private static string getAssemblyByKey(string key)
        {
            string sTmp = ConfigurationManager.AppSettings[key];
            return sTmp;           
        }
    }
}
